#pragma once
#include <QString>
#include <QIcon>
#include <QUuid>
#include <QDateTime>
#include <QFile>
#include <QFileInfo>
//创建一个命名空间
namespace model{

////////////////////////////////////////////////////////////
/// 工具函数，后面很多模块都会用到
///////////////////////////////////////////////////////////
///


static inline QString getFileName(const QString& path){
    QFileInfo fileInfo(path);
    return fileInfo.fileName();
}

// 封装一个“宏”作为打印日志的方式
#define TAG QString("[%1:%2]").arg(model::getFileName(__FILE__), QString::number(__LINE__))
#define LOG() qDebug().noquote() << TAG


//要求函数的定义如果在 .h中，必须加satic 或者inline (当然两个都加也可以)，避免链接阶段出现函数重定义的问题
static inline QString formatTime(int64_t timestamp){
    //先把时间戳，转化成QDateTime 对象
    QDateTime dateTime = QDateTime::fromSecsSinceEpoch(timestamp);
    //把QDateTime格式转成 格式化时间
    return dateTime.toString("MM-dd HH:mm:ss");
}

static inline int64_t getTime(){
    return QDateTime::currentSecsSinceEpoch();
}

//将QbyteArray转成Qicon
static inline QIcon makeIcon(const QByteArray& byteArray){
    QPixmap pixmap;    //提供很多关于图片的处理方法
    pixmap.loadFromData(byteArray);
    QIcon icon(pixmap);
    return icon;
}

//读写文件操作
//从指定文件中读取所有二进制内容，得到一个QbyteArrag
static inline QByteArray loadFileToByteArray(const QString &path){
    QFile file(path);
    bool ok = file.open(QFile::ReadOnly);
    if(!ok){
        LOG()<<"文件打开失败!";
        return QByteArray();
    }
    QByteArray content = file.readAll();
    file.close();
    return content;
}
//将QbyteArray内容写道指定文件
static inline void writeByteArrayToFile(const QString& path, const QByteArray& content){
    QFile file(path);
    bool ok = file.open(QFile::WriteOnly);
    if(!ok){
        LOG()<<"文件打开失败!";
        return;
    }
    file.write(content);
    file.flush();    //记得刷新缓冲区
    file.close();
    return;
}
////////////////////////////////////////////////////////////
/// 用户信息
///////////////////////////////////////////////////////////
class UserInfo{
public:
    QString userId = "";
    QString nicnname = "";    //昵称
    QString description = "";   //个性签名
    QString phone = "";   //手机号
    QIcon avatar;   //用户头像
};


////////////////////////////////////////////////////////////
/// 消息信息
///////////////////////////////////////////////////////////
enum MessageType{
    TEXT_TYPE,
    IMAGE_TYPE,
    FILE_TYPE,
    SPEECH_TYPE,
    UNKNOWN_TYPE    //错误类型
};

class Message{
public:
    QString messageId = "";   //消息的编号
    QString chatSessionId = "";  //消息所属会话的编号
    QString time = "";        //消息的时间，通过格式化时间来表示
    MessageType messageType = TEXT_TYPE;   //消息类型
    UserInfo sender;       //消息发送者的信息
    QByteArray content;   //消息的正文内容
    QString fileId = "";      //表示文件的身份标识，文件语音图片可能会很大，因此用ID表示，需要再获取。
    QString fileName = "";    //文件名称，当文件时才有效。其他为"" ，用于另存为功能


    static QString makeId(){
        return "M"+QUuid::createUuid().toString().sliced(25, 12);
    }


    //工厂模式，构造函数不够用，构造点  平面执教坐标，极坐标
    static Message makeMessage(MessageType messageType, const QString& chatSessionId,
                               const UserInfo& sender, const QByteArray& content, const QString& extraInfo){
        if(messageType == TEXT_TYPE){
            return makeTextMessage(chatSessionId, sender, content);
        }else if(messageType == SPEECH_TYPE){
            return makeSpeechMessage(chatSessionId, sender, content);
        }else if(messageType == FILE_TYPE){
            return makeFileMessage(chatSessionId, sender, content, extraInfo);
        }else if(messageType == IMAGE_TYPE){
            return makeImageMessage(chatSessionId, sender, content);
        }else{
            return Message();
        }
    }

    //生成文本消息
    static Message makeTextMessage(const QString& chatSessionId, const UserInfo& sender,const QByteArray& content){
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.messageType = TEXT_TYPE;
        message.content = content;
        //fileID后续使用的时候进一步设置
        message.fileId = "";
        message.fileName = "";
        return message;
    }

    //生成语音消息
    static Message makeSpeechMessage(const QString& chatSessionId, const UserInfo& sender,const QByteArray& content){
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.messageType = SPEECH_TYPE;
        message.content = content;
        //fileID后续使用的时候进一步设置
        message.fileId = "";
        message.fileName = "";
        return message;
    }

    //生成图片消息
    static Message makeImageMessage(const QString& chatSessionId, const UserInfo& sender,const QByteArray& content){
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.messageType = IMAGE_TYPE;
        message.content = content;
        //fileID后续使用的时候进一步设置
        message.fileId = "";
        message.fileName = "";
        return message;
    }

    //生成文件消息
    static Message makeFileMessage(const QString& chatSessionId, const UserInfo& sender,const QByteArray& content, const QString& fileName){
        Message message;
        message.messageId = makeId();
        message.chatSessionId = chatSessionId;
        message.sender = sender;
        message.time = formatTime(getTime());
        message.messageType = FILE_TYPE;
        message.content = content;

        //fileID后续使用的时候进一步设置
        message.fileId = "";
        message.fileName = fileName;

        return message;
    }
};


////////////////////////////////////////////////////////////
/// 会话信息(聊天的会话)
///////////////////////////////////////////////////////////
class ChatSessionInfo{
public:
    QString chatSessionId = "";   //绘画编号
    QString chatSessionName = "";  //会话名字，单聊就是对方的昵称，群聊就是群聊名称
    Message lastMessage;   //表示最新消息
    QIcon avatar;         //会话的头像，单聊是对方的头像，群聊是群的头像
    QString userId = "";        //如果是单聊，表示对方ID，群聊表示所有ID
};

}  //end model
